package request

import (
	"awesomeProject2/src/test2020/stats/constant"
	"awesomeProject2/src/test2020/stats/util"
	"awesomeProject2/src/test2020/stats/write"
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"time"
)

type Context struct {
	Path      string      `json:"path"`            // 存储地址
	Url       string      `json:"url"`             // 请求地址
	Child     []Context   `json:"child,omitempty"` // 子级
	ChildSize int         `json:"childSize"`       // 子级数量
	InitValid bool        `json:"initValid"`       // 已经初始化验证
	Request   bool        `json:"request"`         // 是否已经请求
	HasChild  bool        `json:"hasChild"`        // 是否存在子级
	HasSearch bool        `json:"hasSearch"`       // 是否检索子级
	Level     int         `json:"level"`           // 层级
	Logs      []write.Log `json:"-"`               // 日志输出
}

// 初始化
func (c *Context) Init() {
	// 读取进度信息
	path := constant.FileDir + "/" + constant.RequestConfigName
	if util.FileExists(path) {
		bt, _ := ioutil.ReadFile(path)
		_ = json.Unmarshal(bt, c)
	}
	c.InitLog()
	// 初始化解析配置
	InitRequestContextParse()
}

// 设置url
func (c *Context) SetUrl(baseUrl string, indexUrl string, pu string) {
	if "" != pu {
		indexUrl = c.SetUrlParse(indexUrl, pu)
	}
	c.Url = baseUrl + indexUrl
	if "index.html" != indexUrl {
		indexUrl = "index/" + indexUrl
	}
	// 处理path
	c.Path = constant.FileDir + indexUrl
	c.InitValid = true
}

func (c *Context) SetLevel(pl int) {
	c.Level = pl + 1
}

func (c *Context) RefreshLevel() {
	c.Level = 1
	if c.HasChild {
		for k := range c.Child {
			c.Child[k].Level = c.Level + 1
			c.Child[k].RefreshChildLevel()
		}
	}
}

func (c *Context) RefreshChildLevel() {
	if c.HasChild {
		for k := range c.Child {
			c.Child[k].Level = c.Level + 1
			c.Child[k].RefreshChildLevel()
		}
	}
}

// 请求
func (c *Context) DoRequest(headers map[string]string) {
	// 未请求
	if !c.InitValid {
		return
	}
	if c.Request {
		c.HandlerChild()
	} else {
		r := Request{headers: headers, url: c.Url}
		fmt.Print("请求：" + r.url)
		bt, err := r.getBytes()
		fmt.Println(" 请求完成")
		if err != nil {
			// 请求失败
			c.Request = false
		} else {
			// 判断文件夹是否存在
			util.CreateDir(c.Path)
			// 写文件
			c.Request = util.WriteFile(c.Path, bt)
		}
		// sleep
		time.Sleep(1 * time.Second)
		if c.Request {
			c.HandlerChild()
		}
	}
}

func (c *Context) HandlerChild() {
	// 解析子级
	c.ParseChild()
	// 处理子级
	c.DoRequestChild(constant.Headers)
	// 通知日志
	go c.NotifyLog()
}

func (c *Context) DoRequestChild(headers map[string]string) {
	if c.HasChild {
		for k := range c.Child {
			c.Child[k].DoRequest(headers)
		}
	}
}

func (c *Context) ParseChild() {
	if c.HasSearch {
		return
	}
	c.HasSearch = true
	child := c.ContextParseChild()
	if child != nil {
		c.Child = child
		c.ChildSize = len(child)
		c.HasChild = true
	} else {
		c.HasChild = false
	}
}

func (c *Context) InitLog() {
	c.Logs = []write.Log{&write.FmtLog{}}
}

func (c *Context) NotifyLog() {
	if c.Logs != nil {
		for _, v := range c.Logs {
			v.Write(c.Copy())
		}
	}
}

func (c *Context) Copy() Context {
	cc := Context{}
	cc.Path = c.Path
	cc.Url = c.Url
	cc.ChildSize = c.ChildSize
	cc.InitValid = c.InitValid
	cc.Request = c.Request
	cc.HasChild = c.HasChild
	cc.HasSearch = c.HasSearch
	return cc
}

// 销毁
func (c *Context) Destroy() {
	// 把进度信息保存起来
	path := constant.FileDir + "/" + constant.RequestConfigName
	var file *os.File
	if !util.FileExists(path) {
		fmt.Println("文件不存在")
		file, _ = os.Create(path)
		bt, _ := json.Marshal(c)
		var out bytes.Buffer
		_ = json.Indent(&out, bt, "", "\t")
		_, _ = file.Write(out.Bytes())
	} else {
		fmt.Println("文件存在")
		file, _ = os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0666)
		bt, _ := json.Marshal(c)
		var out bytes.Buffer
		_ = json.Indent(&out, bt, "", "\t")
		_, _ = file.Write(out.Bytes())
	}
	defer func() {
		_ = file.Close()
	}()
}
